package com.zlq.cn.service.un;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.push.model.v20160801.PushRequest;
import com.aliyuncs.utils.ParameterHelper;
import com.zlq.cn.config.Config;
import com.zlq.cn.config.FinderConfiguration;
import org.apache.commons.lang3.StringUtils;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

import static org.apache.commons.lang3.StringUtils.EMPTY;

@Service
public class PushService {

    private static final Map<String, Long> PUSH_IOS_APP_KEY_MAP = new HashMap<>();

    private final FinderConfiguration finderConfiguration;

    @Resource
    private DefaultAcsClient defaultAcsClient;

    public PushService(FinderConfiguration finderConfiguration) {
        this.finderConfiguration = finderConfiguration;
        PUSH_IOS_APP_KEY_MAP.put(null, finderConfiguration.getPushIosAppKey());
        PUSH_IOS_APP_KEY_MAP.put(Config.PROJECT_LOVERS, finderConfiguration.getLoversPushIosAppKey());
    }

    @Bean
    public DefaultAcsClient defaultAcsClient() {
        return new DefaultAcsClient(
                DefaultProfile.getProfile(finderConfiguration.getPushRegionId(),
                        finderConfiguration.getAliyunAccessKeyId(),
                        finderConfiguration.getAliyunAccessSecret()));
    }

    public void pushAccount(String project, Integer accountId, String title, String body, JSONObject extParameters) {
        List<Integer> accountIds = new ArrayList<>();
        accountIds.add(accountId);
        pushAccount(project, accountIds, title, body, extParameters);
    }

    public void pushAccount(String project, List<Integer> accountIds, String title, String body, JSONObject extParameters) {
        String target = "ACCOUNT";
        String targetValue = joinAccount(accountIds.iterator());
        if (StringUtils.isEmpty(targetValue)) return;
        //pushAndroid(target, targetValue, title, body, handExtParameters(extParameters));
        pushIosAccount(project, target, targetValue, title, body, handExtParameters(extParameters));
    }

    /*public void pushTag(Integer accountId, String title, String body, JSONObject extParameters) {
        String target = "TAG";
        String targetValue = String.format("%s_tag_%d", dqConfiguration.getPushProfile(), accountId);
        pushAndroid(target, targetValue, title, body, handExtParameters(extParameters));
        pushIosAccount(target, targetValue, title, body, handExtParameters(extParameters));
    }*/

    private String handExtParameters(JSONObject extParameters) {
        return extParameters == null ? "" : JSON.toJSONString(extParameters);
    }

    private void pushAndroid(String target, String targetValue, String title, String body, String extParameters) {
        PushRequest pushRequest = new PushRequest();
        pushRequest.setAppKey(finderConfiguration.getPushAndroidAppKey());
        pushRequest.setTarget(target); //推送目标: DEVICE:推送给设备; ACCOUNT:推送给指定帐号,TAG:推送给自定义标签; ALL: 推送给全部
        pushRequest.setTargetValue(targetValue); //49067根据Target来设定，如Target=DEVICE, 则对应的值为 设备id1,设备id2. 多个值使用逗号分隔.(帐号与设备有一次最多100个的限制)
        pushRequest.setPushType("NOTICE"); // 消息类型 MESSAGE NOTICE
        pushRequest.setDeviceType("ANDROID"); // 设备类型 ANDROID iOS ALL.
        pushRequest.setTitle(title); // 消息的标题
        pushRequest.setBody(body); // 消息的内容
        pushRequest.setAndroidNotifyType("BOTH");//通知的提醒方式 "VIBRATE" : 震动 "SOUND" : 声音 "BOTH" : 声音和震动 NONE : 静音
        pushRequest.setAndroidOpenType("NONE"); //点击通知后动作 "APPLICATION" : 打开应用 "ACTIVITY" : 打开AndroidActivity "URL" : 打开URL "NONE" : 无跳转
        pushRequest.setAndroidMusic("default"); // Android通知音乐
        pushRequest.setAndroidPopupActivity("com.diqwl.push.PopupPushActivity");//设置该参数后启动辅助弹窗功能, 此处指定通知点击后跳转的Activity（辅助弹窗的前提条件：1. 集成第三方辅助通道；2. StoreOffline参数设为true）
        pushRequest.setAndroidPopupTitle(title);
        pushRequest.setAndroidPopupBody(body);
        pushRequest.setAndroidNotificationChannel("diqwl");
        pushRequest.setAndroidExtParameters(extParameters); //设定通知的扩展属性。(注意 : 该参数要以 json map 的格式传入,否则会解析出错)
//        startPush(pushRequest);
    }

    private void pushIosAccount(String project, String target, String targetValue, String title, String body, String extParameters) {
        PushRequest pushRequest = new PushRequest();
        pushRequest.setAppKey(PUSH_IOS_APP_KEY_MAP.get(project));
        pushRequest.setTarget(target); //推送目标: DEVICE:推送给设备; ACCOUNT:推送给指定帐号,TAG:推送给自定义标签; ALL: 推送给全部
        pushRequest.setTargetValue(targetValue); //49067根据Target来设定，如Target=DEVICE, 则对应的值为 设备id1,设备id2. 多个值使用逗号分隔.(帐号与设备有一次最多100个的限制)
        pushRequest.setPushType("NOTICE"); // 消息类型 MESSAGE NOTICE
        pushRequest.setDeviceType("iOS"); // 设备类型 ANDROID iOS ALL.
        pushRequest.setTitle(title); // 消息的标题
        pushRequest.setBody(body); // 消息的内容
        pushRequest.setIOSBadge(1); // iOS应用图标右上角角标
        pushRequest.setIOSMusic("default"); // iOS通知声音
        //pushRequest.setIOSSubtitle(title);//iOS10通知副标题的内容
//        pushRequest.setIOSNotificationCategory("iOS10 Notification Category");//指定iOS10通知Category
        pushRequest.setIOSMutableContent(true);//是否允许扩展iOS通知内容
        pushRequest.setIOSApnsEnv(finderConfiguration.getPushIosProfile());//iOS的通知是通过APNs中心来发送的，需要填写对应的环境信息。"DEV" : 表示开发环境 "PRODUCT" : 表示生产环境
        pushRequest.setIOSRemind(true); // 消息推送时设备不在线（既与移动推送的服务端的长连接通道不通），则这条推送会做为通知，通过苹果的APNs通道送达一次。注意：离线消息转通知仅适用于生产环境
        pushRequest.setIOSRemindBody(body);//iOS消息转通知时使用的iOS通知内容，仅当iOSApnsEnv=PRODUCT && iOSRemind为true时有效
        pushRequest.setIOSExtParameters(extParameters); //通知的扩展属性(注意 : 该参数要以json map的格式传入,否则会解析出错)
        startPush(project, pushRequest);
    }

    private void startPush(String project, PushRequest pushRequest) {
        Date pushDate = new Date(System.currentTimeMillis()); // 30秒之间的时间点, 也可以设置成你指定固定时间
        String pushTime = ParameterHelper.getISO8601Time(pushDate);
        pushRequest.setPushTime(pushTime); // 延后推送。可选，如果不设置表示立即推送
        String expireTime = ParameterHelper.getISO8601Time(new Date(System.currentTimeMillis() + 12 * 3600 * 1000)); // 12小时后消息失效, 不会再发送
        pushRequest.setExpireTime(expireTime);
        pushRequest.setStoreOffline(true); // 离线消息是否保存,若保存, 在推送时候，用户即使不在线，下一次上线则会收到
        try {
            defaultAcsClient.getAcsResponse(pushRequest);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private String joinAccount(final Iterator<Integer> iterator) {
        if (iterator == null) {
            return null;
        }
        if (!iterator.hasNext()) {
            return EMPTY;
        }
        final Integer first = iterator.next();
        if (!iterator.hasNext()) {
            return Objects.toString(getPushAccount(first), "");
        }
        final StringBuilder buf = new StringBuilder(256); // Java default is 16, probably too small
        if (first != null) {
            buf.append(first);
        }

        while (iterator.hasNext()) {
            buf.append(',');
            final Integer obj = iterator.next();
            if (obj != null) {
                buf.append(getPushAccount(obj));
            }
        }
        return buf.toString();
    }

    private String getPushAccount(Integer accountId) {
        return String.format("%s_account_%d", finderConfiguration.getPushProfile(), accountId);
    }
}
